package com.example.canvasball;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;


public class MainActivity extends Activity implements  OnTouchListener {
	
	EvalBoard eBoard;
	int _x, _y;
	private float coodx;
    private float coody;
    protected static int mTileSize;//kich thuoc
    public final int intX=1;
    public final int intO=2;
    protected static int mXTileCount;//cout X
    protected static int mYTileCount;//cout Y
    private static int mXOffset;
    private static int mYOffset;
    public static int[] DScore = { 0, 1, 9, 81, 729 };
    public static int[] AScore ={ 0, 2, 18, 162, 1458 };
    public Bitmap[] mtBitmap;
    public boolean flagContinue;
    
    public static int maxDepth = 4;//11
    public static int maxMove = 2;//3
    public int depth = 0;
    
    public boolean fWin = false;
    public int fEnd = 0;
    
    private int[][] mTileGrid;
    private final Paint mPaint = new Paint();
    public MyCustomPanel Mview;
    
    Coordinate[] PCMove = new Coordinate[maxMove];
    Coordinate[] HumanMove = new Coordinate[maxMove];
    Coordinate[] WinMove = new Coordinate[maxDepth];
    Coordinate[] LoseMove = new Coordinate[maxDepth];
    Coordinate[] LineEnd=new Coordinate[2];
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        LinearLayout layout = (LinearLayout) findViewById(R.id.idLinearLayout);
        Mview = new MyCustomPanel(this);
        final Button btNewgame= (Button) this.findViewById(R.id.btNew);
        final Button btOptions= (Button) this.findViewById(R.id.btOptions);
        final Button btUndo= (Button) this.findViewById(R.id.btUndo);
//        ViewGroup.LayoutParams params = 
//                            new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,
//                                                       LayoutParams.FILL_PARENT);
        Mview.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        layout.addView(Mview);
        
//        addContentView(view, params);
        
        Mview.setOnTouchListener(this);
        this.clickNewGame(btNewgame);
        this.clickOptions(btOptions);
        this.clickUndo(btUndo);
//        btNewgame.setOnClickListener(l);
//        view.setOnClickListener(this);
//        view.on
    }
    private class MyCustomPanel extends View {

        public MyCustomPanel(Context context) {
            super(context);
            mTileSize=24;
            resetTiles(3);
            loadTile(intX,context.getResources().getDrawable(R.drawable.x));
            loadTile(intO,context.getResources().getDrawable(R.drawable.o));
            clearTiles();
//            initGame();
        }

        
		@Override
		protected void onDraw(Canvas canvas) {
			// TODO Auto-generated method stub
			super.onDraw(canvas);
			Paint paint= new Paint();
			paint.setColor(Color.GREEN);
			paint.setStrokeWidth(1);
//			System.out.println(mTileSize+" "+mXTileCount+" "+mYTileCount);
			for(int dx=0;dx<mXTileCount;dx++){
				for(int dy=0;dy<mYTileCount;dy++){
					canvas.drawLine(dx*mTileSize, dy*mTileSize, (dx+1)*mTileSize, dy*mTileSize, paint);
					canvas.drawLine(dx*mTileSize, dy*mTileSize, dx*mTileSize, (dy+1)*mTileSize, paint);
					if(dx==mXTileCount-1){
						canvas.drawLine((dx+1)*mTileSize, dy*mTileSize, (dx+1)*mTileSize, (dy+1)*mTileSize, paint);
					}
					if(dy==mYTileCount-1){
						canvas.drawLine(dx*mTileSize, (dy+1)*mTileSize, (dx+1)*mTileSize, (dy+1)*mTileSize, paint);
					}
				}
				
			}
			paint.setColor(Color.RED);
			paint.setStrokeWidth(8);
			if(fEnd!=0){
				int detaX=mTileSize/2;
				int detaY=mTileSize/2;
				canvas.drawLine(LineEnd[0].getX()*mTileSize+detaX, LineEnd[0].getY()*mTileSize+detaY, LineEnd[1].getX()*mTileSize+detaX, LineEnd[1].getY()*mTileSize+detaY, paint);
			}
//			canvas.drawRect(10, 10, 50, 50, paint);
//			canvas.drawCircle(50, 50, 10, paint);
//			canvas.drawCircle(coodx, coodx, 10, paint);
			for (int x = 0; x < mXTileCount; x += 1) {
	            for (int y = 0; y < mYTileCount; y += 1) {
	                if (mTileGrid[x][y] > 0) {
	                    canvas.drawBitmap(mtBitmap[mTileGrid[x][y]], 
	                    		mXOffset + x * mTileSize,
	                    		mYOffset + y * mTileSize,
	                    		mPaint);
	                }
	            }
	        }
		}

		@Override
		protected void onSizeChanged(int w, int h, int oldw, int oldh) {
			// TODO Auto-generated method stub
			 	mXTileCount = (int) Math.floor(w / mTileSize);
		        mYTileCount = (int) Math.floor(w / mTileSize);
//				mTileSize=(int) Math.floor(w / mTileSize);
//		        mXOffset = (mTileSize / 2);//in the center position
		        mXOffset=0;
//		        mYOffset = mTileSize  / 2;
		        mYOffset=0;

		        mTileGrid = new int[mXTileCount][mYTileCount];
		        initGame();
		}
    }
//    public boolean onTouch(View v, MotionEvent event) {
//        x = event.getX();
//        y = event.getY();
//        
//        v.invalidate();
//        return true;
//    }
	public void clickNewGame(Button bt) {
		bt=(Button) this.findViewById(R.id.btNew);
		bt.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View view) {
				// TODO Auto-generated method stub
				Toast.makeText(MainActivity.this, "NewGame", Toast.LENGTH_LONG).show();
				fEnd=0;
				depth=0;
				fWin=false;
				
				initGame();
				Mview.invalidate();
			}
			
		});
	}

	public void clickOptions(Button bt) {
		bt=(Button) this.findViewById(R.id.btOptions);
		bt.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View view) {
				// TODO Auto-generated method stub
				AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
		        builder.setTitle("Info");
//		        builder.setMessage("YOU CHOOSE LEVEL: EASIEST,EASY,MEDIUM,HARD AND HARDEST");
		       
//		        builder.setSingleChoiceItems(items, checkedItem, listener)
		        CharSequence[] items=new CharSequence[5];
		        items[0]="Easyest";
		        items[1]="Easy";
		        items[2]="Medium";
		        items[3]="Hard";
		        items[4]="Hardest";
		        builder.setSingleChoiceItems(items,0, new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int item) {
						// TODO Auto-generated method stub
						switch(item){
						case 0:
							maxDepth=1;
							maxMove=2;
							break;
						case 1:
							maxDepth=2;
							maxMove=2;
							break;
						case 2: 
							maxDepth=3;
							maxMove=2;
							break;
						case 3: 
							maxDepth=4;
							maxMove=3;
							break;
						case 4: 
							maxDepth=6;
							maxMove=3;
							break;
						}
						
					}
		                             
		        });
		        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
		            public void onClick(DialogInterface dialog, int which) {
		                // TODO Auto-generated method stub                            
		            }                        
		        });
		        builder.show();
				
			}
			
		});
	}
	 
	public void clickUndo(Button bt){
		bt=(Button) this.findViewById(R.id.btUndo);
		bt.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View view) {
				// TODO Auto-generated method stub
			}
			
		});
	}
	@Override
 	public boolean onTouch(View v, MotionEvent e) {
		// TODO Auto-generated method stub
		coodx=e.getX();
		coody=e.getY();
		//condition in board
		if(coodx>=0&&coodx<=mXTileCount*mTileSize&&coody>=0&&coody<=mYTileCount*mTileSize&&fEnd == 0 ){
			int dx=(int) (coodx/mTileSize);
			int dy=(int) (coody/mTileSize);
			if(mTileGrid[dx][dy]==0){
				setTile(1,dx,dy);
				if(CheckEnd(dx,dy)==1){
					
					fEnd = 1;
					v.invalidate();
					ShowMessage("YOU WIN");
					return false;
				}
				AI();
                if (fWin)
                {
                    _x = WinMove[0].getX();
                    _y = WinMove[0].getY();
                }
                else
                {
                    EvalChessBoard(2,  eBoard);
                    Coordinate temp = new Coordinate();
                    temp = eBoard.MaxPos();
                    _x = temp.getX();
                    _y = temp.getY();
                }
                mTileGrid[_x][ _y] = 2;
                if (CheckEnd(_x, _y) == 2) {
                	
                	fEnd = 2; 
                	v.invalidate();
                	ShowMessage("YOU LOSE");
                	return false;
                }
				v.invalidate();
			}
		}
		
		return false;
		
	}
	public void loadTile(int key, Drawable tile) {
        Bitmap bitmap = Bitmap.createBitmap(mTileSize, mTileSize, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        tile.setBounds(0, 0, mTileSize, mTileSize);
        
        tile.draw(canvas);
        
        this.mtBitmap[key] = bitmap;
    }
	public void setTile(int tileindex, int x, int y) {
        mTileGrid[x][y] = tileindex;
    }
	public void resetTiles(int tilecount) {
		mtBitmap = new Bitmap[tilecount];
    }
	public void clearTiles() {
        for (int x = 0; x < mXTileCount; x++) {
            for (int y = 0; y < mYTileCount; y++) {
                setTile(0, x, y);
            }
        }
    }
	public void initGame(){
		for (int r = 0; r < mXTileCount ; r++)
            for (int c = 0; c < mYTileCount; c++)
            	mTileGrid[r][c] = 0;
		eBoard=new EvalBoard(mXTileCount,mYTileCount);
		LineEnd=new Coordinate[2];
	}
	public int CheckEnd(int cl, int rw)
     {
//		System.out.println("check End");
         int r = 0, c = 0;
         int i;
         boolean human, pc;
         
         while (c < mXTileCount - 5)
         {
             human = true; pc = true;
             for (i = 0; i < 5; i++)
             {
                 if (mTileGrid[cl][ c + i] != 1)
                     human = false;
                 if (mTileGrid[cl][ c + i] != 2)
                     pc = false;
             }
             if (human) {
            	 LineEnd[0]=new Coordinate(cl,c);
            	 LineEnd[1]=new Coordinate(cl,c+4);
            	 return 1;
             }
             if (pc) {
            	 LineEnd[0]=new Coordinate(cl,c);
            	 LineEnd[1]=new Coordinate(cl,c+4);
            	 return 2;
             }
             c++;
         }
         
         
         while (r < mYTileCount - 5)
         {
             human = true; pc = true;
             for (i = 0; i < 5; i++)
             {
                 if (mTileGrid[r + i][ rw] != 1)
                     human = false;
                 if (mTileGrid[r + i][ rw] != 2)
                     pc = false;
             }
             if (human) {
            	 LineEnd[0]=new Coordinate(r,rw);
            	 LineEnd[1]=new Coordinate(r+4,rw);
            	 return 1;
             }
             if (pc) {
            	 LineEnd[0]=new Coordinate(r,rw);
            	 LineEnd[1]=new Coordinate(r+4,rw);
            	 return 2;
             }
             r++;
         }
         
         //Check duong cheo xuong
         r = rw; c = cl;
         while (r > 0 && c > 0) { r--; c--; }
         while (r <= mYTileCount - 5 && c <= mXTileCount - 5)
         {
             human = true; pc = true;
             for (i = 0; i < 5; i++)
             {
                 if (mTileGrid[c + i][ r + i] != 1)
                     human = false;
                 if (mTileGrid[c + i][r + i] != 2)
                     pc = false;
             }
             if (human) {
            	 LineEnd[0]=new Coordinate(c,r);
            	 LineEnd[1]=new Coordinate(c+4,r+4);
            	 return 1;
             }
             if (pc) {
            	 LineEnd[0]=new Coordinate(c,r);
            	 LineEnd[1]=new Coordinate(c+4,r+4);
            	 return 2;
             }
             r++; c++;
         }
         
         //Check duong cheo len
         r = rw; c = cl;
         while (r < mYTileCount - 1 && c > 0) { r++; c--; }
         while (r >= 4 && c <= mXTileCount - 5)
         {
             human = true; pc = true;
             for (i = 0; i < 5; i++)
             {
                 if (mTileGrid[r - i][ c + i] != 1)
                     human = false;
                 if (mTileGrid[r - i][ c + i] != 2)
                     pc = false;
             }
             if (human) {
            	 LineEnd[0]=new Coordinate(r,c);
            	 LineEnd[1]=new Coordinate(r-4,c+4);
            	 return 1;
             }
             if (pc){
            	 LineEnd[0]=new Coordinate(r,c);
            	 LineEnd[1]=new Coordinate(r-4,c+4);
            	 return 2;
             }
             r--; c++;
         }
         return 0;
     }
     public void EvalChessBoard(int player, EvalBoard eBoard)
     {
         int rw, cl, ePC, eHuman;
         eBoard.ResetBoard();
         
         //Danh gia theo hang
         for (rw = 0; rw < mYTileCount; rw++)            
             for (cl = 0; cl < mXTileCount - 4; cl++)
             {
                 ePC = 0; eHuman = 0;
                 for (int i = 0; i < 5; i++)
                 {
                     if (mTileGrid[rw][ cl + i] == 1) eHuman++;//tinh so quan nguoi danh
                     if (mTileGrid[rw][ cl + i] == 2) ePC++;//tinh so quan may danh
                 }

                 if (eHuman * ePC == 0 && eHuman != ePC)//xet hang co nguoi hoac may chua danh quan nao
                 {
                     for (int i = 0; i < 5; i++)
                     {
                         if (mTileGrid[rw][ cl + i] == 0) // Neu o chua duoc danh
                         {
                             if (eHuman == 0)//neu nguoi chua danh-tinh val cho pc bao nhieu
                                 if (player == 1)//player la nguoi
                                     eBoard.mBoard[rw][ cl + i] += DScore[ePC];//tinh val may danh
                                 else eBoard.mBoard[rw][ cl + i] += AScore[ePC];//player la may-tang val nhanh hon
                             if (ePC == 0)//neu may chua danh-tinh val cho human bao nhieu
                                 if (player == 2)//player la may
                                 {
                                	 int cli=cl+i;
//                                	 System.out.println("(rw,cl)="+"("+rw+","+cli+")");
//                                	 System.out.println("eHuman="+eHuman);
//                                	 System.out.println("DScore(eHuman)="+DScore[eHuman]);
////                                	 System.out.println("mBoard[rw][cl]="+eBoard.mBoard[rw][ cl + i]);
//                                	 System.out.println("width="+eBoard.width);
                                     eBoard.mBoard[rw][ cl + i] += DScore[eHuman];
                                    
                                 }
                                 else eBoard.mBoard[rw][ cl + i] += AScore[eHuman];//player la nguoi-tang val nhanh hon
                             if (eHuman == 4 || ePC == 4)//truong hop co 4 quan--tang val len gap doi
                                 eBoard.mBoard[rw][ cl + i] *= 2;
                         }
                     }
                     
                 }                
              }

         //Danh gia theo cot
         for (cl = 0; cl < mXTileCount; cl++)
             for (rw = 0; rw < mYTileCount - 4; rw++)
             {
                 ePC = 0; eHuman = 0;
                 for (int i = 0; i < 5; i++)
                 {
                     if (mTileGrid[rw + i][ cl] == 1) eHuman++;
                     if (mTileGrid[rw + i][ cl] == 2) ePC++;
                 }

                 if (eHuman * ePC == 0 && eHuman != ePC)
                 {
                     for (int i = 0; i < 5; i++)
                     {
                         if (mTileGrid[rw + i][ cl] == 0) // Neu o chua duoc danh
                         {
                             if (eHuman == 0)
                                 if (player == 1)
                                     eBoard.mBoard[rw + i][ cl] += DScore[ePC];
                                 else eBoard.mBoard[rw + i][ cl] += AScore[ePC];
                             if (ePC == 0)
                                 if (player == 2)
                                     eBoard.mBoard[rw + i][ cl] += DScore[eHuman];
                                 else eBoard.mBoard[rw + i][ cl] += AScore[eHuman];
                             if (eHuman == 4 || ePC == 4)
                                 eBoard.mBoard[rw + i][ cl] *= 2;
                         }
                     }

                 }
             }

         //Danh gia duong cheo xuong
         for (cl = 0; cl < mXTileCount - 4; cl++)
             for (rw = 0; rw < mYTileCount - 4; rw++)
             {
                 ePC = 0; eHuman = 0;
                 for (int i = 0; i < 5; i++)
                 {
                     if (mTileGrid[rw + i][ cl + i] == 1) eHuman++;
                     if (mTileGrid[rw + i][ cl + i] == 2) ePC++;
                 }

                 if (eHuman * ePC == 0 && eHuman != ePC)
                 {
                     for (int i = 0; i < 5; i++)
                     {
                         if (mTileGrid[rw + i][ cl + i] == 0) // Neu o chua duoc danh
                         {
                             if (eHuman == 0)
                                 if (player == 1)
                                     eBoard.mBoard[rw + i][ cl + i] += DScore[ePC];
                                 else eBoard.mBoard[rw + i][ cl + i] += AScore[ePC];
                             if (ePC == 0)
                                 if (player == 2)
                                     eBoard.mBoard[rw + i][ cl + i] += DScore[eHuman];
                                 else eBoard.mBoard[rw + i][ cl + i] += AScore[eHuman];
                             if (eHuman == 4 || ePC == 4)
                                 eBoard.mBoard[rw + i][ cl + i] *= 2;
                         }
                     }

                 }
             }

         //Danh gia duong cheo len
         for (rw = 4; rw < mYTileCount; rw++)
             for (cl = 0; cl < mXTileCount - 4; cl++)
             {
                 ePC = 0; eHuman = 0;
                 for (int i = 0; i < 5; i++)
                 {
                     if (mTileGrid[rw - i][ cl + i] == 1) eHuman++;
                     if (mTileGrid[rw - i][ cl + i] == 2) ePC++;
                 }

                 if (eHuman * ePC == 0 && eHuman != ePC)
                 {
                     for (int i = 0; i < 5; i++)
                     {
                         if (mTileGrid[rw - i][ cl + i] == 0) // Neu o chua duoc danh
                         {
                             if (eHuman == 0)
                                 if (player == 1)
                                     eBoard.mBoard[rw - i][ cl + i] += DScore[ePC];
                                 else eBoard.mBoard[rw - i][ cl + i] += AScore[ePC];
                             if (ePC == 0)
                                 if (player == 2)
                                     eBoard.mBoard[rw - i][ cl + i] += DScore[eHuman];
                                 else eBoard.mBoard[rw - i][ cl + i] += AScore[eHuman];
                             if (eHuman == 4 || ePC == 4)
                                 eBoard.mBoard[rw - i][ cl + i] *= 2;
                         }
                     }

                 }
             }
         
     }
     
     public void ShowMessage(String ms){
     	AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("Info");
        builder.setMessage(ms);
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub                            
            }                        
        });
        builder.show();
     }
     public void AI()
     {
//         for (int i = 0; i < maxMove; i++)
//         {
////             WinMove[i] = new Coordinate();
//             PCMove[i] = new Coordinate();
//             HumanMove[i] = new Coordinate();
//         }
//         for(int i=0;i<maxDepth;i++){
//        	 WinMove[i] = new Coordinate();
//         }
         depth = 0;
         FindMove();
         //MessageBox.Show(depth.ToString());
     }
     private void FindMove()
     {
//    	 System.out.println("depth="+depth);
         if (depth >= maxDepth) return;
         depth++;
         fWin = false;
         boolean fLose = false;
         Coordinate pcMove = new Coordinate();
         Coordinate humanMove = new Coordinate();
         int countMove = 0;
//         System.out.println("eBoard.width="+eBoard.width);
         EvalChessBoard(2,  eBoard);//ham luong gia cua player=2(may)

         //Lay ra MaxMove buoc di co diem cao nhat
         Coordinate temp = new Coordinate();
         for (int i = 0; i < maxMove; i++)// lay maxMove diem 
         {
             temp = eBoard.MaxPos();
             PCMove[i] = temp;//move diem cao nhat vao tap PCMove
             eBoard.mBoard[temp.getX()][ temp.getY()] = 0;//thiet lap lai luong gia =0;
         }

         //Lay nuoc di trong PCMove[] ra danh thu
         countMove = 0;
         while (countMove < maxMove)
         {
//        	 System.out.println("countMove,depth="+countMove+","+depth);
             pcMove = PCMove[countMove];countMove+=1;
             mTileGrid[pcMove.getX()][ pcMove.getY()] = 2;//danh thu vi tri (x,y)=2 
//             WinMove.(pcMove, depth - 1);//thiet lap gia tri cho nuoc di tot nhat.
//             System.out.println("lenwin="+WinMove.length);
//             WinMove[depth-1].toString();
//             System.out.println("countMove="+countMove);
//             System.out.println("pcMove=("+pcMove.getX()+","+pcMove.getY()+")");
//             System.out.println("depth:"+depth);
//             System.out.println("maxDepth:"+maxDepth);
             WinMove[depth - 1]=pcMove;
             
             //Tim cac nuoc di toi uu cua nguoi
             eBoard.ResetBoard();//khoi dong lai ham luong la.
             EvalChessBoard(1, eBoard);
             //Lay ra maxMove nuoc di co diem cao nhat cua nguoi
             for (int i = 0; i < maxMove; i++)
             {
                 temp = eBoard.MaxPos();
                 HumanMove[i] = temp;
                 eBoard.mBoard[temp.getX()][ temp.getY()] = 0;
             }
             //Danh thu cac nuoc di
             for (int i = 0; i < maxMove; i++)
             {
                 humanMove = HumanMove[i];
                 mTileGrid[humanMove.getX()][ humanMove.getY()] = 1;
                 if (CheckEnd(humanMove.getX(), humanMove.getY()) == 2)
                 {
                     fWin = true;
                     //MessageBox.Show("fwin" + fWin.ToString());
                 }
                 if (CheckEnd(humanMove.getX(), humanMove.getY()) == 1)
                 {
                     fLose = true;
                     //MessageBox.Show("flose" + fLose.ToString());
                 }
                 if (fLose)
                 {
                	 mTileGrid[pcMove.getX()][ pcMove.getY()] = 0;
                	 mTileGrid[humanMove.getX()][ humanMove.getY()] = 0;
                     break;
                 }
                 if (fWin)
                 {
                	 mTileGrid[pcMove.getX()][ pcMove.getY()] = 0;
                	 mTileGrid[humanMove.getX()][ humanMove.getY()] = 0;
                     return;
                 }
                 FindMove();//de quy
                 mTileGrid[humanMove.getX()][ humanMove.getY()] = 0;//khoi phuc lai nuoc di human
             }
             mTileGrid[pcMove.getX()][ pcMove.getY()] = 0;//khoi phuc lai nuoc di pc

         }

     }
}